﻿using System.Collections.Generic;
using System.Linq;
using SIG.Repository;
using SIG.Infrastructure.Logging;
using SIG.Infrastructure.Cache;
using SIG.Infrastructure.Configs;
using SIG.Resources;
using SIG.Model.Store;
using System.Linq.Expressions;
using System;
using SIG.Basic.Extensions;
using System.Threading;
using System.Threading.Tasks;
using SIG.Resources.Admin;

namespace SIG.Service
{
    public class GoodsService :  EntityService<Goods>, IGoodsService
    {
       
        private readonly IGoodsRepository _goodsRepository;
        private readonly ILoggingService _loggingService;
        private readonly ICacheService _cacheService;

        public GoodsService(IGoodsRepository categoryRepository, ILoggingService loggingService, ICacheService cacheService)
            : base(categoryRepository, cacheService, loggingService)
        {           
            _goodsRepository = categoryRepository;
            _loggingService = loggingService;
            _cacheService = cacheService;
        }


        public IEnumerable<Goods> LatesterGoods(int count)
        {
            var key = $"{EntityNames.Goods}s_Recommend";

            if (!SettingsManager.Store.EnableCaching)
            {
                return _goodsRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            }

            if (_cacheService.IsSet(key))
            {
                return (List<Goods>)_cacheService.Get(key);

            }

            var goodsList = _goodsRepository.GetPagedElements(0, count, p => p.CreatedDate, p => p.Active, false).ToList();
            _cacheService.Set(key, goodsList, SettingsManager.Store.CacheDuration);


            return goodsList;
        }

        public List<Goods> GetPagedActiveElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {

            //get list count
            var keyCount = $"{EntityNames.Goods}_ListCount_Active_{keyword}_{categoryId}";

            var totalIQuery = _goodsRepository.GetAllElements().Where(g=>g.Active);
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Name.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Store.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Store.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Goods}_List_Active_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Goods> goods;
            Expression<Func<Goods, bool>> filter = g => g.Active;
            Expression<Func<Goods, bool>> filterByKeyword = g => g.Name.Contains(keyword);
            Expression<Func<Goods, bool>> filterByCategory = g => g.CategoryId == categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Store.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    goods = (List<Goods>)_cacheService.Get(key);

                }
                else
                {
                    goods = _goodsRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.GoodsCategory).ToList();
                    _cacheService.Set(key, goods, SettingsManager.Store.CacheDuration);
                }
            }
            else
            {
                goods = _goodsRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.GoodsCategory).ToList();
            }

            return goods;

        }

        public async Task<IList<Goods>> GetActiveElementsAync(CancellationToken cancellationToken = default(CancellationToken))
        {
            //get list
            var key = $"{EntityNames.Goods}_List_Active";

            IList<Goods> goodslist;
            if (SettingsManager.Store.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    goodslist = (IList<Goods>)_cacheService.Get(key);

                }
                else
                {
                    var goods = await _goodsRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.GoodsCategory);
                    goodslist = goods.ToList();
                    _cacheService.Set(key, goodslist, SettingsManager.Store.CacheDuration);
                }
            }
            else
            {
                var goods = await _goodsRepository.GetFilteredElementsAsync(m => m.Active, cancellationToken, g => g.GoodsCategory);
                goodslist = goods.ToList();
            }

            return goodslist;

        }

        public List<Goods> GetPagedElements(int pageIndex, int pageSize, string keyword, int? categoryId, out int totalCount)
        {
                       
            //get list count
            var keyCount = $"{EntityNames.Goods}_ListCount_{keyword}_{categoryId}";

            var totalIQuery = _goodsRepository.GetAllElements();
            if (!string.IsNullOrEmpty(keyword))
                totalIQuery = totalIQuery.Where(g => g.Name.Contains(keyword));
            if (categoryId > 0)
                totalIQuery = totalIQuery.Where(g => g.CategoryId == categoryId);

            if (SettingsManager.Store.EnableCaching)
            {
                if (_cacheService.IsSet(keyCount))
                {
                    totalCount = (int)_cacheService.Get(keyCount);
                }
                else
                {
                    totalCount = totalIQuery.Count();
                    _cacheService.Set(keyCount, totalCount, SettingsManager.Store.CacheDuration);
                }
            }
            else
            {
                totalCount = totalIQuery.Count();
            }


            //get list
            var key = $"{EntityNames.Goods}_List_{pageIndex}_{pageSize}_{keyword}_{categoryId}";

            List<Goods> goods;
            Expression<Func<Goods, bool>> filter = g => true;
            Expression<Func<Goods, bool>> filterByKeyword = g=>g.Name.Contains(keyword);
            Expression<Func<Goods, bool>> filterByCategory = g => g.CategoryId==categoryId;

            if (!string.IsNullOrEmpty(keyword))
                filter = filter.AndAlso(filterByKeyword);
            if (categoryId > 0)
                filter = filter.AndAlso(filterByCategory);


            if (SettingsManager.Store.EnableCaching)
            {
                if (_cacheService.IsSet(key))
                {
                    goods = (List<Goods>)_cacheService.Get(key);

                }
                else
                {
                    goods = _goodsRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g=>g.GoodsCategory).ToList();
                    _cacheService.Set(key, goods, SettingsManager.Store.CacheDuration);
                }
            }
            else
            {
                goods = _goodsRepository.GetPagedElements(pageIndex, pageSize, (c => c.CreatedDate), filter, false, g => g.GoodsCategory).ToList();
            }

            return goods;            

        }

       
    }
}
